package com.tc.vms.utils;

import com.tc.vms.log.VmsClientLogger;
import org.slf4j.Logger;

/**
 * Created by yonghua.zhang on 2015/11/18.
 */
public abstract class ServiceThread implements Runnable {
    private final static Logger LOGGER = VmsClientLogger.getLog();

    protected final Thread thread;

    protected volatile boolean hasNotified = false;

    protected volatile boolean isStopped = false;

    private static final int JOIN_TIME = 60 * 1000;

    public ServiceThread() {
        this.thread = new Thread(this, this.getServiceName());
    }

    public abstract String getServiceName();

    public void start() {
        this.thread.start();
    }

    public void stop() {
        stop(false);
    }

    public void shutdown() {
        shutdown(false);
    }

    public void stop(final boolean interrupt) {
        LOGGER.info("Stop the thread of [" + this.getServiceName() + "] with the interrupt lag is " + interrupt);
        this.isStopped = true;
        synchronized (this) {
            if (!hasNotified) {
                this.hasNotified = true;
                this.notify();
            }
        }

        if (interrupt) {
            this.thread.interrupt();
        }

    }

    public void makeStop() {
        this.isStopped = true;
        LOGGER.info("makeStop the thread of [" + this.getServiceName() + "].");
    }

    public static int getJoinTime() {
        return JOIN_TIME;
    }

    public void shutdown(final boolean interrupt) {
        LOGGER.info("Shutdown the thread of [" + this.getServiceName() + "] with the interrupt lag is " + interrupt);
        this.isStopped = true;

        synchronized (this) {
            if (!hasNotified) {
                this.hasNotified = true;
                this.notify();
            }
        }

        try {
            if (interrupt) {
                this.thread.interrupt();
            }

            long beginTime = System.currentTimeMillis();

            if (!this.thread.isDaemon()) {
                this.thread.join(getJoinTime());
            }
            long eclipseTime = System.currentTimeMillis() - beginTime;

            LOGGER.info("Join current thread " + this.getServiceName() + " eclipses time(ms) [" + eclipseTime +
                    "]. Default JoinTime = " + getJoinTime());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    public void wakeup() {
        synchronized (this) {
            if (!hasNotified) {
                hasNotified = true;
                this.notify();
            }
        }
    }

    protected void waitForRunning(long interval) {
        synchronized (this) {
            if (hasNotified) {
                hasNotified = false;
                return;
            }
            try {
                this.wait(interval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                hasNotified = false;
            }

        }

    }

    public boolean isStopped() {
        return isStopped;
    }
}
